
#ifndef __SQLITE_DB_H
#define __SQLITE_DB_H

#include <vector>
#include "../sqlite/sqlite3.h"
#include "../iface/debug.h"
#include "SQLiteAutoLock.h"

// Maybe write in hourly backups somewhere?

/** An interface to an SQLite3 database.
 * 
 * For thread safety a mutex is given to globally lock the database
 * during SQL execution. The class gives both thread safe and unsafe
 * methods so that it is possible for external caller to use the same
 * sqlite3_mutex_enter and splite3_mutex_leave calls to enforce
 * operation atomicity externally, helping to keep a consistent state
 * across multiple tables and even possibly multiple databases. */
class SQLiteDB
{
   public:
      SQLiteDB(const char *filename, int persists);
      ~SQLiteDB();
      int sqlInstantExec(const char *query);
      int sqlInstantExecf(const char *query, ...);
      std::vector<char *> *sqlScanRowText(const char *csql);
      std::vector<char *> *sqlScanRowTextf(const char *csql, ...) PRINTF_LIKE(2, 3);
      std::vector<char *> *sqlScanAllText(const char *csql);
      std::vector<char *> *sqlScanAllTextf(const char *csql, ...) PRINTF_LIKE(2, 3);
      void backup();
      static int isWhitespace(char wht);
      static void stringSanitiser(char *sanstr);
      void ensureTablesAreCreated(int notables, ...);
      int sqlGetSingleIntf(int *result, const char *csql, ...) PRINTF_LIKE(3, 4);
      int sqlGetSingleDoublef(double *result, const char *csql, ...) PRINTF_LIKE(3, 4);
      int sqlGetSingleStringf(char **result, const char *csql, ...) PRINTF_LIKE(3, 4);
      int sqlCheckTableExists(const char *tablename, ...) PRINTF_LIKE(2, 3);
      /** Retrieves the automatic locking mechanism for use in the
       * call:
       * 
       * SQLiteAutoLock thislock(sqlitedb->getAutoLock());
       * 
       * which would generate a reference counted recursive database
       * lock.
       * 
       * @return The constant SQLiteAutoLock master instance to copy
       * construct from. */
      const SQLiteAutoLock &getAutoLock() { return *autolock; }
   protected:
      /** The main database pointer from SQLite3. */
      sqlite3 *db;
      /** The file name for SQL commands to clone the database to be
       * dumped to in an effort to provide a backup. */
      char *dumpfilename;
   private:
      /** The automatic database locking mechanism encapsulated in the
       * auto lock class. */
      SQLiteAutoLock *autolock;
      /** The main database mutex from SQLite3. */
      sqlite3_mutex *dbmutex;
      /** This class cannot be copied. */
      SQLiteDB(const SQLiteDB &o);
      /** This class cannot be copied. */
      SQLiteDB &operator=(const SQLiteDB &o);
      int dumpDatabaseToSQL(const char *filename);
      int dumpTableToSQL(FILE *FP, const char *tablename);
      int loadSQL(const char *filename);
      int sqlScanRowStatement(sqlite3_stmt *sql, const char *rowformat, ...); // this one isn't printf-like
      std::vector<char *> *sqlScanRowStatement(sqlite3_stmt *sql);
      std::vector<char *> *sqlScanAllStatement(sqlite3_stmt *sql);
      int sqlGetSingleIntStatement(int *result, sqlite3_stmt *sql);
      int sqlGetSingleDoubleStatement(double *result, sqlite3_stmt *sql);
      int sqlGetSingleStringStatement(char **result, sqlite3_stmt *sql);
      sqlite3_stmt *sqlCompile(const char *query);
      int sqlFinalize(sqlite3_stmt *sql);
};

#endif
